ImageGear Professional DLL for Windows
ISIS Tag Examples

This section shows examples of working with tags and choices:

Scanning a Page and Saving Group 4 Data

This example shows how to scan a page and make sure that the file is saved with CCITT Group 4 compression, whether the scanner outputs Group 4 compressed data or uncompressed data. If the scanner is capable of outputting Group 4 compressed data, this example constructs an ISIS pipe that does not do compression, and it turns on Group 4 compression in the scanner driver. If the scanner cannot output Group 4 compressed data, this example constructs a pipe that includes the necessary compression drivers and does not attempt to turn on compression in the scanner driver. This sample assumes that a scanner has already been loaded and its handle is hScan.

 
Copy Code
LONG lComp;
WORD wCount, iIndex;
BOOL bGroup4 = FALSE;
HISISDRV hWrite;

/* We can assume that IG_ISIS_TAG_COMPRESSION will always be a list, */
/* so we didn't do a IG_ISIS_choice_get_flags. */

/* If the following call fails, then there is no compression */
/* available from the scanner: */
if (!IG_ISIS_choice_get_count(hScan, IG_ISIS_TAG_COMPRESSION, &wCount)) {
for (iIndex = 0; iIndex < wCount; iIndex++) {

/* Loop thru all choices and put into lComp: */
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_COMPRESSION, iIndex, &lComp);

/* If any value of lComp is G4, set bGroup4 to TRUE: */
if (lComp == IG_ISIS_COMPRESSION_G4)
bGroup4 = TRUE ;
break;
}
}

/* If bGroup4 is True, make a pipe that writes the file without */
/* compression. Set the scanner driver to Group 4. */
if (bGroup4) {
IG_ISIS_drv_load_init_pipe(0, "PIXFPACK", &hWrite, 0);
IG_ISIS_drv_link(hScan, hWrite);
IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_COMPRESSION, 0, IG_ISIS_COMPRESSION_G4);
}

/* Otherwise, make a pipe that includes G4 compression. Don't try */
/* to turn on compression in the scanner. */
else {
IG_ISIS_drv_load_init_pipe(0, "RAS2RUN|RUN2G4|PIXFPACK", &hWrite, 0);
IG_ISIS_drv_link(hScan, hWrite);
IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_COMPRESSION, 0, IG_ISIS_COMPRESSION_NONE);
}

/* Set the output filename and type */
IG_ISIS_tag_set_ascii(hFileWriter, IG_ISIS_TAG_OUTNAME, 0, (char FAR *)"TST.TIF");
IG_ISIS_tag_set_long(hFileWriter, IG_ISIS_TAG_FILETYPE, 0, IG_ISIS_TAG_FILETYPE_TIFF);

/* Invoke the pipe */
IG_ISIS_run_zone(hScan, buffer, sizeof buffer);

/* Clean up when done */
IG_ISIS_drv_link(hScan, 0);
IG_ISIS_drv_unload_pipe(hWrite);

Setting a Scanning Area

One way to allow a user to set the scanning area is to call the toolkit's built-in Set Scanning Area dialog box by using the IG_ISIS_drv_area_dialog() function. If you would rather use your own interface to set the scanning area, this example will show you how. (The source code sample SCANTEST.C defines a function for setting scanning area and is a good source of additional information.)

The following example shows how to pick a 3" wide by 5" high rectangle as close to the center of a page as possible.

Note that the first step in this example is to set the X position to zero. This is done in case some other code has already defined a scanning area. To reflect the currently-available legal IMAGEWIDTH settings, the legal values of IMAGEWIDTH change if XPOSITION changes. (This is another tag dependency that must be remembered.) The sample does not test whether IG_ISIS_TAG_IMAGEWIDTH is a list or a range, because in ISIS drivers, it is always a range.

Finally, note that all ISIS measurements are in pixels and dots per inch, regardless of how the scanner wants the measurements specified. ISIS drivers make this conversion, if necessary.

 
Copy Code
LONG lHigh, lLow, lStep, lLeft, lWidth, lTop, lLength;
AT_ISIS_RAT rat;

/* Reset X position to 0 in case some other region was defined. */
IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_XPOSITION, 0, 0L);

/* Query the width values. */
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_IMAGEWIDTH, IG_ISIS_CHOICE_HIGH, &lHigh);
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_IMAGEWIDTH, IG_ISIS_CHOICE_LOW, &lLow);
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_IMAGEWIDTH, IG_ISIS_CHOICE_STEP, &lStep);

/* Get the current X position. */
IG_ISIS_tag_get_rational(hScan, IG_ISIS_TAG_XRESOLUTION, 0, &rat);

/* Multiply 3" by resolution (after converting to an integer). */
lWidth = 3*(rat.Num+rat.Denom-1)/rat.Denom ;

if (lWidth > lHigh-lLow)
/* scanner cannot scan an area 3" large */
return -1;

/* Compute the left edge of the page to the nearest step. */
lLeft = (lHigh - lLow - lWidth) / 2 ; /* Find middle */
lLeft = lLeft - (lLeft % lStep) ; /* Adjust to closest legal step */

/* Set the left edge (X position). */
IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_XPOSITION, 0, lLeft);

/* Get the new high value for image width */
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_IMAGEWIDTH, IG_ISIS_CHOICE_HIGH, &lHigh);
/* Set image width to actual width or to the new high value, */
/* whichever is less. */
lWidth = lWidth - (lWidth % lStep) ; /* adjust width to closest */
if (lWidth > lHigh) /* legal step value. */
lWidth = lHigh ;
IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_IMAGEWIDTH, 0, lWidth);

/* Repeat everything to set the height. */

IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_YPOSITION, 0, 0L);

IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_IMAGELENGTH, IG_ISIS_CHOICE_HIGH, &lHigh);
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_IMAGELENGTH, IG_ISIS_CHOICE_LOW, &lLow);
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_IMAGELENGTH, IG_ISIS_CHOICE_STEP, &lStep);

IG_ISIS_tag_get_rational(hScan, IG_ISIS_TAG_YRESOLUTION, 0, &rat);

lLength = 5*(rat.Num+rat.Denom-1)/rat.Denom ;

if (lLength > lHigh-lLow)
return -1;

lTop = (lHigh - lLow - lWidth) / 2; /* Find middle */
lTop = lTop - (lTop % lStep); /* Adjust to closest legal step */

IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_YPOSITION, 0, lTop);

IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_IMAGELENGTH, IG_ISIS_CHOICE_HIGH, &lHigh);

lLength = lLength - (lLength % lStep) ; /* adjust length to closest */
if (lLength > lHigh) /* legal step value */
lLength = lHigh ;
IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_IMAGELENGTH, 0, lLength);

In the above example, note that the step value for these tags depends on the mode of the scanner. PIXDFLT does not work with fractional bytes of image data; therefore, binary scanning will typically have step values of eight pixels (one byte). The above example truncates to the step to the left, so if the region to be scanned does not fall on a step value, it will be shifted to the nearest step to the left (a maximum of seven pixels).

ISIS scanner drivers default to 300 dots per inch (dpi) if this resolution is available. If 300 dpi is not available, the default resolution is the nearest value that is less 300 dpi. Scanner driver use RATIONAL image resolution values that generally have a denominator of 1, so it is generally safe to work only with the numerator. (Keep in mind that ISIS drivers will accept a RATIONAL value with a denominator of any integer value.) Even though the PixTools/Scan toolkit normally uses RATIONAL values with a denominator of 1, it is quite common for the PixTools/View toolkit to work with TIFF files that have resolutions of, for example, 7,200,000/10,000. This is a valid image resolution according to the TIFF specification.

Some scanners allow X and Y resolutions to be different from one another. To determine if this is the case for the current scanner, you can query the choices for X resolution and Y resolution. On scanners that do not support independent X and Y resolutions, there will only be one choice for the Y resolution, and its value will be the last value set for X resolution. (Note that Standard mode faxes are 200 x 100 dpi.)

Making a List of Available Color Formats

The following example makes a list of available color formats from the current scanner. Note that for this code to work it is necessary to set the value of IG_ISIS_TAG_SAMPLESPERPIXEL in order to find out the choices for IG_ISIS_TAG_BITSPERSAMPLE . (Each value of IG_ISIS_TAG_SAMPLESPERPIXEL could cause the choice for IG_ISIS_TAG_BITSPERSAMPLE to return a different set of choices.)

 
Copy Code
main()
{
LONG lBits, lSamps, lValue, lFlags;
WORD wCount, iIndex;
HISISDRV hScan;

/* Load and init, for example, Nikon scanner driver */
IG_ISIS_drv_load_init_pipe(0, "NIKON", &hScan, 0);

/* Find out how many choices there are for SAMPLESPERPIXEL */
IG_ISIS_choice_get_count(hScan, IG_ISIS_TAG_SAMPLESPERPIXEL, &wCount);

/* Get and set values for SAMPLESPERPIXEL one at a time */
for (iIndex = 0; iIndex < wCount; iIndex++) {
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_SAMPLESPERPIXEL, iIndex,
&lSamps);
IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_SAMPLESPERPIXEL, 0, lSamps);

/* If SAMPLESPERPIXEL is 1, then must be binary, grayscale */
/* or palette color. */
if (lSamps==1) {
LONG lValue;
/* binary, grayscale, or palette color */

/* IG_ISIS_TAG_BITSPERSAMPLE is normally a list, and the following list
* logic will also handle the case where it is a range. However
* it is presented here with specific list and range code to
* demonstrate how to process both types. IG_ISIS_TAG_RESOLUTION is, for
* example, a more common tag that you would want to be able to
* process as both a list and a range.
*/
/* Determine whether BITSPERSAMPLE is a list or a range */
IG_ISIS_choice_get_flags(hScan, IG_ISIS_TAG_BITSPERSAMPLE, &lFlags);

/* Handle case where BITSPERSAMPLE is a list */
if (lFlags & IG_ISIS_CONT_LIST) {
WORD iIndex, wCount;
LONG lBits;
IG_ISIS_choice_get_count(hScan, IG_ISIS_TAG_BITSPERSAMPLE, &wCount);
for (iIndex = 0; iIndex < wCount; iIndex++) {
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_BITSPERSAMPLE,
iIndex, &lBits);
if (lBits==1)
printf("Binary is supported\n");
else
printf("%d-bit grayscale is supported\n",
(int)lBits);
}
}
/* Handle case where BITSPERSAMPLE is a range */
else
if (lFlags & IG_ISIS_CONT_RANGE) {
LONG lLow, lHigh, lStep, lBits;
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_BITSPERSAMPLE,
IG_ISIS_CHOICE_LOW, &lLow);
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_BITSPERSAMPLE,
IG_ISIS_CHOICE_HIGH, &lHigh);
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_BITSPERSAMPLE,
IG_ISIS_CHOICE_STEP, &lStep);
for (lBits = lLow; lBits <= lHigh; lBits += lStep)
if (lBits==1)
printf("Binary is supported\n");
else
printf("%d-bit grayscale is supported\n",
(int)lBits);
}
}

/* If SAMPLESPERPIXEL is 3, then must be color */
else
if (lSamps=3) {
LONG lValue;
/* color */

/* Determine whether BITSPERSAMPLE is a list or a range */
IG_ISIS_choice_get_flags(hScan, IG_ISIS_TAG_BITSPERSAMPLE, &lFlags);

/* Handle case where BITSPERSAMPLE is a list */
if (lFlags & IG_ISIS_CONT_LIST) {
WORD iIndex, wCount;
LONG lBits;
IG_ISIS_choice_get_count(hScan, IG_ISIS_TAG_BITSPERSAMPLE, &wCount);
for (iIndex = 0; iIndex < wCount; iIndex++) {
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_BITSPERSAMPLE,
iIndex, &lBits);

/* The number of bits in color is 3 times the BITSPERSAMPLE */
printf("%d-bit color is supported\n",
(int)lBits*3);
}
}

/* Handle case where BITSPERSAMPLE is a range */
else
if (lFlags & IG_ISIS_CONT_RANGE) {
LONG lLow, lHigh, lStep, lBits;
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_BITSPERSAMPLE,
IG_ISIS_CHOICE_LOW, &lLow);
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_BITSPERSAMPLE,
IG_ISIS_CHOICE_HIGH, &lHigh);
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_BITSPERSAMPLE,
IG_ISIS_CHOICE_STEP, &lStep);
for (lBits = lLow; lBits <= lHigh; lBits += lStep)

/* The number of bits in color is 3 times the BITSPERSAMPLE */
printf("%d-bit color is supported\n",
(int)lBits*3);
}
}
/* Probably will never see this case: If scanner returns other than */
/* 1 or 3 SAMPLESPERPIXEL, print number of samples scanner supports */
else {
printf("Scanner supports %d-sample color\n",
(int)lSamps);
}
}
IG_ISIS_drv_unload_pipe(hScan);
}

Listing a Scanner's Tags

PixTools/Scan has functions that read and write the values of all tags in a scanner driver. The following sample shows how to get a list of all tags that a scanner supports.

ISIS allows your application to query a scanner and tell it to give you a list of all tags which exist in a driver. The tag that contains this list is tag number zero (0). The following example shows how to use this special tag to get a list of all tags supported in a driver:

 
Copy Code
LONG lNumTags, dwIndex;
LONG lTagNum;
WORD wType;
char FAR *ucTagType;

/* ask for tag zero's length; that's the number of tags that */
/* the scanner supports */
IG_ISIS_tag_get_length(hScan, 0, &lNumTags);

/* Get the tag number and the tag type for each of lNumTags */
for (dwIndex = 0; dwIndex < lNumTags; dwIndex++) {
IG_ISIS_tag_get_long(hScan, 0, dwIndex, &lTagNum);
IG_ISIS_tag_get_type(hScan, (AT_MODE) lTagNum, &wType);
switch (wType) {
case IG_ISIS_TAG_TYPE_BYTE: ucTagType="Byte"; break;
case IG_ISIS_TAG_TYPE_SHORT: ucTagType="Word"; break;
case IG_ISIS_TAG_TYPE_LONG: ucTagType="Long"; break;
case IG_ISIS_TAG_TYPE_RATIONAL: ucTagType="Rational"; break;
case IG_ISIS_TAG_TYPE_STRING: ucTagType="Ascii"; break;
default: ucTagType="Unknown"; break;
}

/* Print the tag number and type, one tag per line */
printf("Tag number %ld is supported, and is of type %s\n",
lTagNum, ucTagType);
}

The above example prints the number and type of each tag. The string representation for the tag name is not in the toolkit. The # defines that associate strings with tag numbers can be found in PIXTAGS.H

Once you have found the type of a tag, you could extend this example to find out its choices. You can also use this method to find all tag values. Another way to do this is to use the library function IG_ISIS_tag_save_file() . This function saves the current value of all scanner state tags for the referenced driver to a file (usually SETSCAN.INI), in a section of the specified name. A corresponding function is IG_ISIS_tag_restore_file() which can be used after a IG_ISIS_tag_save_file() to restore the values of all tags to their previous saved values. These two functions used together can save and restore the state of an application's settings for a driver.

Checking a Scanner Driver for 8-Bit Grayscale

The following example shows how to determine whether or not eight-bit grayscale is available from a scanner:

 
Copy Code
/* 1-sample-per-pixel is always allowed (it's needed for binary) */
/* Set SAMPLESPERPIXEL to 1 */
IG_ISIS_tag_set_long(hScan, IG_ISIS_TAG_SAMPLESPERPIXEL, 0, 1L);

/* how many options exist for BITSPERSAMPLE? */
IG_ISIS_choice_get_count(hScan, IG_ISIS_TAG_BITSPERSAMPLE, &wCount);
for (i=0;i<wCount;i++) {

/* Get each value of IG_ISIS_TAG_BITSPERSAMPLE */
IG_ISIS_choice_get_long(hScan, IG_ISIS_TAG_BITSPERSAMPLE, i, &lValue);

/* If a value of 8 is found, stop looking--8-bit gray is supported */
if (lValue==8)
break;
}
if (i<wCount) {
/* 8-bit gray is available */
}
else {
/* 8-bit gray is not available */
}

Displaying a List of Dither Patterns

The following example displays a list of dither patterns that a driver supports:

 
Copy Code
WORD i,j;
char lpcBuffer[128];

/* ASCII tags are always represented as lists */

IG_ISIS_choice_get_count(hDriver,IG_ISIS_TAG_DITHER,&i);
for (j=0; j<i; j++) {
IG_ISIS_choice_get_ascii(hDriver,IG_ISIS_TAG_DITHER,j,lpcBuffer);
printf("%d. %s\n",j,lpcBuffer);
}

Displaying a List of X Resolutions

The following example displays all of the X resolution values that a driver supports:

 
Copy Code
DWORD dwFlags;
WORD wCount;
int i;
AT_ISIS_RAT ratValue1,ratValue2,ratValue3;
/* RATIONAL tags can be represented as a range or list */

IG_ISIS_choice_get_flags(hDriver,IG_ISIS_TAG_XRESOLUTION,&dwFlags);
if (dwFlags & IG_ISIS_CONT_RANGE) {

/* Choices are represented as a range. when a driver supports a
large number of choices (such as resolution or zoning
information), and when the choices are represented as a list,
then accessing the choice values through the special indexes
(LOW, HIGH, STEP) will be much more efficient. */

IG_ISIS_choice_get_rational(hDriver, IG_ISIS_TAG_XRESOLUTION, IG_ISIS_CHOICE_LOW,
&ratValue1);
IG_ISIS_choice_get_rational(hDriver, IG_ISIS_TAG_XRESOLUTION, IG_ISIS_CHOICE_HIGH,
&ratValue2);
IG_ISIS_choice_get_rational(hDriver, IG_ISIS_TAG_XRESOLUTION, IG_ISIS_CHOICE_STEP,
&ratValue3);

/* give ratValue1 and ratValue3 a common denominator */
if (ratValue3.Denom != ratValue1.Denom) {
ratValue1.Num *= ratValue3.Denom;
ratValue1.Denom *= ratValue3.Denom;
ratValue3.Num *= ratValue1.Denom;
ratValue3.Denom *= ratValue1.Denom;
}

while (ratValue1.Num * ratValue2.Denom <= ratValue2.Num *
ratValue1.Denom) {
printf("%ld / %ld\n", ratValue1.Num , ratValue1.Denom);
ratValue1.Num += ratValue3.Num;
}

} else /* if (dwFlags & IG_ISIS_CHOICE_LIST) */ {
/* Choices are represented as a list. Note that this code
would work even if the choices are represented as a range. */

IG_ISIS_choice_get_count(hDriver,IG_ISIS_TAG_XRESOLUTION,&wCount);
for (i=0; i<wCount; i++) {
IG_ISIS_choice_get_rational(hDriver,IG_ISIS_TAG_XRESOLUTION,i,&ratValue1);
printf("%ld / %ld\n", ratValue1.Num, ratValue1.Denom);
}
}

 

 


©2015. Accusoft Corporation. All Rights Reserved.

Send Feedback